﻿using System.Configuration;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using System.Web.Http;
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security.OAuth;
using SDCloudSolution.SDCloud.BusinessLayer.Identity;
using SDCloudSolution.SDCloud.BusinessLayer.Interfaces;

namespace SDCloudSolution.SDCloud.WebApi.Providers
{
    public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
    {
        private IClientApplicationComponent _clientApplicationComponent;

        protected IClientApplicationComponent ClientApplicationComponent
        {
            get
            {
                return _clientApplicationComponent
                       ?? (_clientApplicationComponent =
                           (IClientApplicationComponent)
                               GlobalConfiguration
                                   .Configuration.DependencyResolver
                                   .GetService(typeof(IClientApplicationComponent)));
            }
        }

        private ApplicationUserManager _userManager;

        protected ApplicationUserManager UserManager
        {
            get
            {
                return _userManager
                       ?? (_userManager =
                           (ApplicationUserManager)
                               GlobalConfiguration
                                   .Configuration.DependencyResolver
                                   .GetService(typeof(ApplicationUserManager)));
            }
        }

        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId;
            string clientSecret;

            context.TryGetFormCredentials(out clientId, out clientSecret);

            if (!string.IsNullOrWhiteSpace(clientId) && !string.IsNullOrWhiteSpace(clientSecret))
            {
                if (ClientApplicationComponent.ValidateApplication(clientId, clientSecret))
                {
                    context.Validated(clientId);
                }   
            }

            return Task.FromResult(0);
        }

        public override async Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
        {
            var application = _clientApplicationComponent.GetByClientId(context.ClientId);
            if (application != null)
            {
                ClaimsIdentity identity;

                if (application.UserId.HasValue)
                {
                    var user = await UserManager.FindByIdAsync(application.UserId.Value);
                    identity = await UserManager.CreateIdentityAsync(user, OAuthDefaults.AuthenticationType);
                }
                else
                {
                    identity = new ClaimsIdentity(new GenericIdentity(context.ClientId, OAuthDefaults.AuthenticationType));   
                }

                identity.AddClaim(new Claim("sdcloud:oauth:clientid", context.ClientId));
                identity.AddClaim(new Claim("sdcloud:oauth:grant", "client_credentials"));

                context.Validated(identity);
            }
        }

        public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            context.Validated();

            return Task.FromResult(0);
        }
    }
}